#pragma once

#include <string>

#define DECLARE_PTR(type, ptr, expr) type* ptr = (type*)(expr);

EXTERN_C const GUID CLSID_VirtualFlashCam;
EXTERN_C const GUID CLSID_SetupCVCameraProp;


// Always create new GUIDs! Never copy a GUID from an example.
DEFINE_GUID(IID_ICVCamera, 0x6a4a26a8, 0x5d60, 
0x48f5,0xa6, 0xea, 0x9a, 0xfa, 0x11, 0xc2, 0xe8, 0xb7);



interface ICVCamera : public IUnknown
{
    STDMETHOD(GetCVCameraPosX)(long *plSat) = 0;
    STDMETHOD(SetCVCameraPosX)(long lSat) = 0;
	STDMETHOD(GetCVCameraPosY)(long *plSat) = 0;
    STDMETHOD(SetCVCameraPosY)(long lSat) = 0;
	STDMETHOD(GetCVCameraWidth)(long *plSat) = 0;
    STDMETHOD(SetCVCameraWidth)(long lSat) = 0;
	STDMETHOD(GetCVCameraHeight)(long *plSat) = 0;
    STDMETHOD(SetCVCameraHeight)(long lSat) = 0;
};


class CVCameraStream;
class CVCamera :   public CSource,public ISpecifyPropertyPages,ICVCamera
{
public:
    //////////////////////////////////////////////////////////////////////////
    //  IUnknown
    //////////////////////////////////////////////////////////////////////////
    static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv);

    IFilterGraph *GetGraph() {return m_pGraph;}
	STDMETHODIMP GetPages(CAUUID *pPages);

//SK
    STDMETHODIMP_(ULONG) AddRef() {  return  GetOwner()->AddRef(); }                                                          \
    STDMETHODIMP_(ULONG) Release() { return GetOwner()->Release(); }
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);

	CCritSec  m_csShared;    // Protects shared data.
    long      m_lSaturation; // Saturation level.

	//see http://msdn.microsoft.com/en-us/library/dd377627%28v=vs.85%29.aspx for implementation details.

	STDMETHOD(GetCVCameraPosX)(long *plSat){ return S_OK;};
	STDMETHOD(SetCVCameraPosX)(long lSat) {return S_OK;};
	STDMETHOD(GetCVCameraPosY)(long *plSat){return S_OK;};
	STDMETHOD(SetCVCameraPosY)(long lSat){return S_OK;};
	STDMETHOD(GetCVCameraWidth)(long *plSat){return S_OK;};
	STDMETHOD(SetCVCameraWidth)(long lSat){return S_OK;};
	STDMETHOD(GetCVCameraHeight)(long *plSat){return S_OK;};
	STDMETHOD(SetCVCameraHeight)(long lSat){return S_OK;};


private:
    CVCamera(LPUNKNOWN lpunk, HRESULT *phr);
};

class CxImage;

class CVCameraStream : public CSourceStream, public IAMStreamConfig, public IKsPropertySet
{
public:

    //////////////////////////////////////////////////////////////////////////
    //  IUnknown
    //////////////////////////////////////////////////////////////////////////
    STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
    STDMETHODIMP_(ULONG) AddRef() { return GetOwner()->AddRef(); }                                                          \
    STDMETHODIMP_(ULONG) Release() { return GetOwner()->Release(); }

    //////////////////////////////////////////////////////////////////////////
    //  IQualityControl
    //////////////////////////////////////////////////////////////////////////
    STDMETHODIMP Notify(IBaseFilter * pSender, Quality q);

    //////////////////////////////////////////////////////////////////////////
    //  IAMStreamConfig
    //////////////////////////////////////////////////////////////////////////
    HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
    HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
    HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
    HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC);

    //////////////////////////////////////////////////////////////////////////
    //  IKsPropertySet
    //////////////////////////////////////////////////////////////////////////
    HRESULT STDMETHODCALLTYPE Set(REFGUID guidPropSet, DWORD dwID, void *pInstanceData, DWORD cbInstanceData, void *pPropData, DWORD cbPropData);
    HRESULT STDMETHODCALLTYPE Get(REFGUID guidPropSet, DWORD dwPropID, void *pInstanceData,DWORD cbInstanceData, void *pPropData, DWORD cbPropData, DWORD *pcbReturned);
    HRESULT STDMETHODCALLTYPE QuerySupported(REFGUID guidPropSet, DWORD dwPropID, DWORD *pTypeSupport);
    
    //////////////////////////////////////////////////////////////////////////
    //  CSourceStream
    //////////////////////////////////////////////////////////////////////////
    CVCameraStream(HRESULT *phr, CVCamera *pParent, LPCWSTR pPinName);
    ~CVCameraStream();

    HRESULT FillBuffer(IMediaSample *pms);
    HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc, ALLOCATOR_PROPERTIES *pProperties);
    HRESULT CheckMediaType(const CMediaType *pMediaType);
    HRESULT GetMediaType(int iPosition, CMediaType *pmt);
    HRESULT SetMediaType(const CMediaType *pmt);
    HRESULT OnThreadCreate(void);
    
private:
    CVCamera *m_pParent;
    REFERENCE_TIME m_rtLastTime;
    HBITMAP m_hBmp;
    CCritSec m_cSharedState;
    IReferenceClock *m_pClock;

	CxImage *image;				//main image
	std::wstring FindExtension(const std::wstring& name);
    HRESULT LoadBackImage(const wchar_t *wcPath);

	int m_width,m_height;

	bool  LoadAndResize();

	int defaultiPos;
	int numCap;


};

extern HINSTANCE g_hInstance;
